import { ref, computed } from 'vue'
import { defineStore } from 'pinia'

function mmToPx(mm) {
  const mmNumber = Number(mm || 0)
  return Math.round(mmNumber * 3.78)
}

function getByPath(obj, path) {
  if (!path) return ''
  const parts = String(path).split('.')
  let cur = obj
  for (const key of parts) {
    if (cur && Object.prototype.hasOwnProperty.call(cur, key)) {
      cur = cur[key]
    } else {
      return ''
    }
  }
  return cur ?? ''
}

function replacePlaceholders(templateString, context) {
  return String(templateString).replace(/\{\{\s*([a-zA-Z0-9_\.]+)\s*\}\}/g, (_m, key) => {
    const val = getByPath(context, key)
    if (val === null || val === undefined) return ''
    return String(val)
  })
}

function renderEach(templateString, context) {
  // Supports: {{#each order.items}} ... {{/each}}
  const eachRegex = /\{\{#each\s+([a-zA-Z0-9_\.]+)\s*\}\}([\s\S]*?)\{\{\/each\}\}/g
  return String(templateString).replace(eachRegex, (_m, path, inner) => {
    const list = getByPath(context, path)
    if (!Array.isArray(list) || list.length === 0) return ''
    return list.map(item => replacePlaceholders(inner, { ...context, item })).join('')
  })
}

export const useReceiptStore = defineStore('receipt', () => {
  const STORAGE_KEY = 'erppos_receipt_templates'
  const templates = ref([])

  function persist() {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(templates.value))
  }

  function initialize() {
    const cached = localStorage.getItem(STORAGE_KEY)
    if (cached) {
      try { templates.value = JSON.parse(cached) || [] } catch { templates.value = [] }
      return
    }
    const defaults = getDefaultTemplates()
    templates.value = defaults
    persist()
  }

  function getDefaultTemplates() {
    const receiptContent = [
      '【{{store.name}}】',
      '收银员：{{cashier.name}}',
      '单号：{{order.sn}}',
      '日期：{{order.date}}',
      '--------------------------------',
      '商品  数量  单价  小计',
      '{{#each order.items}}- {{item.name}} x{{item.qty}}  ¥{{item.price}}  ¥{{item.subtotal}}\n{{/each}}',
      '--------------------------------',
      '合计：¥{{order.total}}',
      '实收：¥{{order.received}}',
      '找零：¥{{order.change}}',
      '谢谢惠顾，欢迎下次光临！',
    ].join('\n')

    const labelContent = [
      '{{product.name}}',
      '¥{{product.price}}',
      '编码：{{product.code}}',
    ].join('\n')

    return [
      {
        id: 'T-rcpt-std',
        type: 'receipt',
        name: '标准小票',
        widthMm: 58, // 58mm 票宽
        fontSize: 12,
        lineHeight: 1.4,
        content: receiptContent,
        isDefault: true,
      },
      {
        id: 'T-label-std',
        type: 'label',
        name: '价格标签',
        labelWidthMm: 50,
        labelHeightMm: 30,
        columns: 3,
        rows: 7,
        gapMm: 2,
        fontSize: 14,
        content: labelContent,
        isDefault: true,
      },
    ]
  }

  function addTemplate(data) {
    const id = 'T' + Date.now()
    const base = {
      id,
      type: data.type || 'receipt',
      name: data.name || '未命名模板',
      isDefault: false,
    }
    const payload = base.type === 'receipt'
      ? {
          widthMm: Number(data.widthMm || 58),
          fontSize: Number(data.fontSize || 12),
          lineHeight: Number(data.lineHeight || 1.4),
          content: String(data.content || ''),
        }
      : {
          labelWidthMm: Number(data.labelWidthMm || 50),
          labelHeightMm: Number(data.labelHeightMm || 30),
          columns: Number(data.columns || 3),
          rows: Number(data.rows || 7),
          gapMm: Number(data.gapMm || 2),
          fontSize: Number(data.fontSize || 14),
          content: String(data.content || ''),
        }
    const tpl = { ...base, ...payload }
    templates.value.unshift(tpl)
    persist()
    return tpl
  }

  function updateTemplate(id, updates) {
    const idx = templates.value.findIndex(t => t.id === id)
    if (idx === -1) return null
    const merged = { ...templates.value[idx], ...updates }
    templates.value[idx] = merged
    persist()
    return merged
  }

  function removeTemplate(id) {
    const idx = templates.value.findIndex(t => t.id === id)
    if (idx === -1) return false
    templates.value.splice(idx, 1)
    persist()
    return true
  }

  function cloneTemplate(id) {
    const tpl = templates.value.find(t => t.id === id)
    if (!tpl) return null
    const copy = { ...tpl, id: 'T' + Date.now(), name: tpl.name + ' - 副本', isDefault: false }
    templates.value.unshift(copy)
    persist()
    return copy
  }

  function setDefault(id) {
    const target = templates.value.find(t => t.id === id)
    if (!target) return
    templates.value.forEach(t => { if (t.type === target.type) t.isDefault = false })
    target.isDefault = true
    persist()
  }

  function getTemplateById(id) {
    return templates.value.find(t => t.id === id) || null
  }

  const receiptTemplates = computed(() => templates.value.filter(t => t.type === 'receipt'))
  const labelTemplates = computed(() => templates.value.filter(t => t.type === 'label'))

  // Sample data for preview
  function getSampleReceiptData() {
    const items = [
      { name: '可口可乐330ml', qty: 2, price: 3.5 },
      { name: '康师傅方便面', qty: 1, price: 4.5 },
      { name: '洗衣粉1kg', qty: 1, price: 18 },
    ].map(x => ({ ...x, subtotal: (Number(x.qty) * Number(x.price)).toFixed(2) }))
    const total = items.reduce((s, x) => s + Number(x.subtotal), 0)
    const received = total
    return {
      store: { name: '旗舰店' },
      cashier: { name: '张三' },
      order: {
        sn: 'S' + new Date().toISOString().replace(/[-:T]/g, '').slice(0, 14),
        date: new Date().toLocaleString('zh-CN'),
        items,
        total: total.toFixed(2),
        received: received.toFixed(2),
        change: (received - total).toFixed(2),
      },
    }
  }

  function getSampleLabelProducts() {
    return [
      { code: 'SKU001', name: '可口可乐', price: 3.5 },
      { code: 'SKU002', name: '康师傅方便面', price: 4.5 },
      { code: 'SKU003', name: '洗衣粉1kg', price: 18 },
      { code: 'SKU004', name: '纸抽3层', price: 6.9 },
      { code: 'SKU005', name: '牛奶250ml', price: 2.9 },
      { code: 'SKU006', name: '矿泉水550ml', price: 2.0 },
    ]
  }

  function renderReceiptHtml(templateLike, dataLike) {
    const tpl = templateLike || templates.value.find(t => t.type === 'receipt' && t.isDefault) || receiptTemplates.value[0]
    const ctx = dataLike || getSampleReceiptData()
    if (!tpl) return { html: '', widthPx: 260, fontSize: 12, lineHeight: 1.4 }
    const afterEach = renderEach(tpl.content, ctx)
    const replaced = replacePlaceholders(afterEach, ctx)
    const html = replaced
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/\n/g, '<br/>')
    return {
      html,
      widthPx: mmToPx(tpl.widthMm || 58),
      fontSize: Number(tpl.fontSize || 12),
      lineHeight: Number(tpl.lineHeight || 1.4),
    }
  }

  function renderLabelGridHtml(templateLike, productsLike) {
    const tpl = templateLike || templates.value.find(t => t.type === 'label' && t.isDefault) || labelTemplates.value[0]
    const products = productsLike || getSampleLabelProducts()
    if (!tpl) return { html: '', gridCss: '', labelCss: '' }
    const labelWidthPx = mmToPx(tpl.labelWidthMm || 50)
    const labelHeightPx = mmToPx(tpl.labelHeightMm || 30)
    const gapPx = mmToPx(tpl.gapMm || 2)

    const singleHtml = (p) => {
      const replaced = replacePlaceholders(String(tpl.content || ''), { product: p })
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/\n/g, '<br/>')
      return `<div class="label-item">${replaced}</div>`
    }
    const labelsHtml = products.map(p => singleHtml(p)).join('')
    const gridCss = `display:grid;grid-template-columns:repeat(${Number(tpl.columns || 3)}, ${labelWidthPx}px);grid-auto-rows:${labelHeightPx}px;gap:${gapPx}px;`
    const labelCss = `font-size:${Number(tpl.fontSize || 14)}px;line-height:1.2;` 
    return { html: labelsHtml, gridCss, labelCss, labelWidthPx, labelHeightPx }
  }

  function openPrintWindow(innerHtml, options = {}) {
    const { widthPx = 300, fontSize = 12, lineHeight = 1.4 } = options
    const html = `<!DOCTYPE html><html><head><meta charset="utf-8"/>
      <title>打印</title>
      <style>
        @page { margin: 8mm; }
        body { margin:0; padding:0; }
        .paper { width: ${widthPx}px; margin: 0 auto; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; font-size: ${fontSize}px; line-height: ${lineHeight}; }
      </style>
    </head><body>
      <div class="paper">${innerHtml}</div>
      <script>window.onload = function(){ setTimeout(()=>{ try{ window.focus(); window.print(); }catch(e){} setTimeout(()=>{ try{ window.close(); }catch(e){} }, 100); }, 100); }<\/script>
    </body></html>`

    // 优先尝试新窗口（大多浏览器在用户点击事件中允许弹窗）
    const printWin = window.open('', '_blank', 'noopener,noreferrer,width=400,height=600')
    if (printWin && printWin.document) {
      const doc = printWin.document
      doc.open()
      doc.write(html)
      doc.close()
      return
    }

    // 降级为隐藏 iframe 打印，避免弹窗被拦截
    const iframe = document.createElement('iframe')
    iframe.style.position = 'fixed'
    iframe.style.right = '0'
    iframe.style.bottom = '0'
    iframe.style.width = '0'
    iframe.style.height = '0'
    iframe.style.border = '0'
    document.body.appendChild(iframe)
    const idoc = iframe.contentWindow?.document || iframe.contentDocument
    if (!idoc) return
    idoc.open()
    idoc.write(html)
    idoc.close()
    setTimeout(() => {
      try {
        iframe.contentWindow?.focus()
        iframe.contentWindow?.print()
      } finally {
        setTimeout(() => { try { document.body.removeChild(iframe) } catch(e){} }, 200)
      }
    }, 150)
  }

  return {
    // state
    templates,

    // getters
    receiptTemplates,
    labelTemplates,

    // lifecycle
    initialize,
    persist,

    // CRUD
    addTemplate,
    updateTemplate,
    removeTemplate,
    cloneTemplate,
    setDefault,
    getTemplateById,

    // render & sample
    getSampleReceiptData,
    getSampleLabelProducts,
    renderReceiptHtml,
    renderLabelGridHtml,
    openPrintWindow,
  }
})


